package com.rabbit.mq.controller;

import com.rabbit.mq.po.Order;
import com.rabbit.mq.producer.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/****************************************
 * 作者：HuMaSiYuan
 * 邮箱：siyueguoji@163.com
 * 日期：2023/10/12 9:02
 * 功能描述：
 ****************************************/
@Tag(name = "RabbitMQ")
@RestController
public class TestController {

    @Autowired
    private PaymentNotifyProducer producer;

    @Autowired
    private PaymentNotifyProducer2 producer2;

    @PostMapping(value = "/sendOrder")
    public void sendOrder(String orderId) {
        this.producer.sendMsg(orderId);
    }

    /**
     * 在实际项目中，我们的系统通常会做集群、分布式或灾备部署。那么就会出现一对多、多对一或多对多的场景。
     * 那么咱们本地如何模拟多对一呢？
     */

    @Operation(summary = "manyToOne")
    @PostMapping(value = "/manyToOne")
    public void many2One(){

        // 发送订单号为偶数的订单
        new Thread(() -> {
            for (int i = 0; i < 20; i += 2) {
                this.producer.sendMsg("支付订单号:[" + i + "]");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        // 发送订单号为奇数的订单
        new Thread(() -> {
            for (int i = 1; i < 20; i += 2) {
                this.producer.sendMsg("支付订单号:[" + i + "]");
                try {
                    Thread.sleep(800);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }


    @Operation(summary = "oneToMany")
    @PostMapping(value = "/oneToMany")
    public void oneToMany(){

        // 一对多其实就是有几个队列发送几次相同的消息
        new Thread(() -> {
            for (int i = 0; i < 20; i ++) {
                this.producer.sendMsg("支付订单号:[" + i + "]");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.producer2.sendMsg("支付订单号:[" + i + "]");
            }
        }).start();
    }

    @Autowired
    private RefundNotifyProducer refundNotifyProducer;

    /**
     * 实际项目中，请求信息可能包含多个字段。为了保证生产者与消费者两端的字段一致性，通常会传递一个对象。
     */
    @Operation(summary = "发送整个对象")
    @PostMapping(value = "/wholeObject")
    public void sendWholeObject(@RequestBody Order o) {
        this.refundNotifyProducer.sender(o);
    }

    @Autowired
    private QueryOrderProducer orderProducer;


    /**
     * 虽然RabbitMQ支持RPC接口调用，但不推荐使用。
     * 原因：
     * 1）RPC默认为单线程阻塞模型，效率极低。
     * 2）需要手动实现多线程消费。
     * @param orderId
     */
    @Operation(summary = "RPC远程调用")
    @PostMapping(value = "/rpc")
    public void rpc(String orderId) {
        this.orderProducer.sender(orderId);
    }
}
